package com.sca.gateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sca.gateway.entity.api.BaseResult;
import com.sca.gateway.utils.JwtUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liuxianfei
 * @since 2020/11/4 15:21
 */
@Setter
@Getter
@Slf4j
@Component
public class JwtFilter implements GlobalFilter {

    private final ObjectMapper objectMapper;

    public JwtFilter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst(JwtUtil.HEADER_AUTHORIZATION);
        if (!StringUtils.isEmpty(token)) {
            try {
                /*
                    1.不再统一鉴权，由各自微服务自行完成
                    2.若请求附带了token，则将token里的信息解析到请求头里，以便后续请求获取
                 */
                Map<String, String> map = JwtUtil.claimsMap(token);
                HttpHeaders headers = HttpHeaders.writableHttpHeaders(exchange.getRequest().getHeaders());
                map.forEach((k, v) -> {
                    if (!headers.containsKey(k)) {
                        headers.put(k, Arrays.stream(new String[]{v}).collect(Collectors.toList()));
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return chain.filter(exchange);
    }

    /**
     * 封装验证失败的返回信息
     *
     * @param response
     * @param result
     */
    private Mono<Void> authError(ServerHttpResponse response, BaseResult<?> result) {
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        String s = "";
        try {
            s = objectMapper.writeValueAsString(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        DataBuffer wrap = response.bufferFactory().wrap(s.getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Flux.just(wrap));
    }

}
